from flask import make_response, request, current_app, jsonify, g

from apps.models.user import User
from libs.jwt_token import decode_auth_token, encode_auth_token
from libs.tools import response


def init_app(app):
    # 初始化 请求

    app.before_request(cross_domain_access_before)
    app.before_request(identify)
    app.after_request(cross_domain_access_after)
    app.teardown_request(logger_info)
    app.register_error_handler(Exception, process_exception)


def cross_domain_access_before():
    # 访问路由跨域请求

    if request.method == 'OPTIONS':
        response = make_response()
        response.headers['Access-Control-Allow-Origin'] = '*'
        response.headers['Access-Control-Allow-Headers'] = 'X-TOKEN'
        response.headers['Access-Control-Max-Age'] = 24 * 60 * 60
        response.headers['Access-Control-Allow-Methods'] = "GET, POST, PUT, DELETE, PATCH"
        return response


def cross_domain_access_after(response):
    # 返回header头

    response.headers['Access-Control-Allow-Origin'] = '*'
    response.headers['Access-Control-Allow-Headers'] = 'Content-Type, X-TOKEN'
    return response


def logger_info(error):
    # 打印日志信息

    try:
        current_app.logger.info('request info'.center(40, '*'))
        current_app.logger.info('User.id = {} end.'.format(g.user.id))
        current_app.logger.info('{} {}'.format(request.method, request.url))
        current_app.logger.info(request.json)
        current_app.logger.info('end request'.center(40, '*'))
    except Exception as exc:
        pass
    return response(status_code=400, code=1, msg=error)


def process_exception(error):
    # 处理 error 返回前端

    current_app.logger.error('error'.center(40, '*'))
    current_app.logger.error('error is {} end.'.format(error))
    current_app.logger.error('error'.center(40, '*'))
    return response(status_code=400, code=1, msg=f'{error}')


def identify():
    # 用户鉴权

    if request.path == '/api/admin/token':
        return None

    header_token = request.headers.get('X-TOKEN')
    if header_token:
        payload = decode_auth_token(header_token)
        if payload and payload.get('data'):
            g.user = User.query.get(payload['data']['id'])
            if not g.user:
                return jsonify(code=401, msg='通过X-TOKEN获取用户失败')
            if g.user.login_time == payload['data']['login_time']:
                g.token = encode_auth_token(g.user.id, g.user.login_time)
                return None
            return response(status_code=401, code=1, msg='TOKEN 失效')
        return response(status_code=401, code=1, msg='验证X-TOKEN失败')
    return response(status_code=401, code=1, msg='未获得X-TOKEN')
